package cn.gyn.gynrpc.core.config;

import cn.gyn.gynrpc.core.api.RegistryCenter;
import cn.gyn.gynrpc.core.provider.ProviderBootstrap;
import cn.gyn.gynrpc.core.provider.ProviderInvoker;
import cn.gyn.gynrpc.core.registry.gyn.GynRegistryCenter;
import cn.gyn.gynrpc.core.transport.SpringBootTransport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;

/**
 * @Configuration是Spring框架提供的注解之一，用于标记一个类是配置类。在配置类中，通常会定义一些Bean的创建和初始化逻辑，以及一些特定的配置信息。
 * 通过@Configuration注解标记的类可以被Spring容器识别为配置类，其中可以使用@Bean注解声明Bean，并进行一些定制化的配置，例如对其他Bean的初始化、配置属性等
 *
 * 通过在provider启动类里引入这个类，就能注入：@Import({ProviderConfig.class})
 */
@Slf4j
@Configuration
@Import({AppConfigProperties.class, ProviderProperties.class, SpringBootTransport.class})
public class ProviderConfig {

    @Value("${server.port:8080}")
    private String port;

    @Autowired
    AppConfigProperties appConfigProperties;

    @Autowired
    ProviderProperties providerConfigProperties;

    @Bean
    ProviderBootstrap ProviderBootstrap() {
        //return new ProviderBootstrap();
        return new ProviderBootstrap(port, appConfigProperties, providerConfigProperties);
    }

    @Bean
    ProviderInvoker providerInvoker(@Autowired ProviderBootstrap providerBootstrap) {
        return new ProviderInvoker(providerBootstrap);
    }

    /**
     * 在spring上下文加载完成后，业务代码执行之前，调用此方法把provider注册到zk，延迟服务暴露，保证注册到zk的服务都可用
     * @return
     */
    //Order 注解提高执行优先级，数越小执行优先级越高
    @Bean
    @Order(Integer.MIN_VALUE)
    public ApplicationRunner providerBootstrap_runner(@Autowired ProviderBootstrap providerBootstrap) {
        return x -> {
            log.info("providerBootstrap_runner starting");
            providerBootstrap.start();
            log.info("providerBootstrap_runner started");
        };
    }

    /**
     * 将服务端的zk注册进来
     * 当ZkRegistryCenter类被创建时，会调用start方法（创建curator的client）,当这个类被销毁时，会调用stop方法（执行client.close()）
     */
    //@Bean(initMethod = "start", destroyMethod = "stop")
    @Bean
    @ConditionalOnMissingBean //这个注解通常用在配置类的方法上，它的作用是当 Spring 容器中缺少指定的 Bean 时，才会执行该方法来创建并添加 Bean。
    public RegistryCenter provider_rc() {
        //return new ZkRegistryCenter();
        return new GynRegistryCenter();
    }


}
